package br.com.iswe.core.jpa;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceException;

import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.orm.jpa.EntityManagerHolder;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import br.com.iswe.core.exp.ISWEBusinessException;

public class JPAUtil {
	
	//singleton instance
	private static JPAUtil instance = null;
	
	//IoC
	private EntityManagerFactory emf;
	
	private JPAUtil(){
		
	}
	
	public static JPAUtil getInstance(){
		if(instance == null){
			instance = new JPAUtil();
		}
		return instance;
	}
	
	
	public void executeInJPAContext(JPAUtilCallback callback){
		
		boolean participate = false;

		if (TransactionSynchronizationManager.hasResource(emf)) {
			// Do not modify the EntityManager: just set the participate flag.
			participate = true;
		}
		else {
			try {
				EntityManager em = emf.createEntityManager();
				TransactionSynchronizationManager.bindResource(emf, new EntityManagerHolder(em));
			}
			catch (PersistenceException ex) {
				throw new DataAccessResourceFailureException("Could not create JPA EntityManager", ex);
			}
		}

		try {
			callback.execute();
		}

		finally {
			if (!participate) {
				EntityManagerHolder emHolder = (EntityManagerHolder)
						TransactionSynchronizationManager.unbindResource(emf);
				//EntityManagerFactoryUtils.closeEntityManager(emHolder.getEntityManager());
				
				EntityManager em = emHolder.getEntityManager();
				
				if (em != null) {
					//logger.debug("Closing JPA EntityManager");
					try {
						em.close();
					}
					catch (PersistenceException exp) {
						//logger.debug("Could not close JPA EntityManager", ex);
						throw new ISWEBusinessException("Could not close JPA EntityManager", exp);
					}
					catch (Throwable exp) {
						//logger.debug("Unexpected exception on closing JPA EntityManager", ex);
						throw new ISWEBusinessException("Unexpected exception on closing JPA EntityManager", exp);
					}
				}
				
			}
		}
	}


	public EntityManagerFactory getEmf() {
		return emf;
	}
	public void setEmf(EntityManagerFactory emf) {
		this.emf = emf;
	}
}
